#!/bin/bash
#
# Copyright 2011, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

prefix=$0
log_file=$prefix.log
baseline_file=$prefix.baseline

function cleanup_output() {
    rm -f $log_file
    rm -f $baseline_file
}

function log() {
    echo "$@"
    append $log_file \# "$@"
    append $baseline_file \# "$@"
}

function expect() {
    append $baseline_file "$@"
}

function append() {
    declare -r file=$1
    shift
    echo "$@" >> $file
}

function run() {
    # strip out carriage returns from adb
    # strip out date/time from ls -l
    "$@" | tr --delete '\r' | sed -E 's/[0-9]{4}-[0-9]{2}-[0-9]{2} +[0-9]{1,2}:[0-9]{2} //' >> $log_file
}

function keystore() {
    declare -r user=$1
    shift
    run adb shell su $user keystore_cli "$@"
}

function list_keystore_directory() {
    run adb shell ls -al /data/misc/keystore
}

function compare() {
    log "comparing $baseline_file and $log_file"
    diff $baseline_file $log_file || (log $tag FAILED && exit 1)
}

function test_basic() {

    #
    # reset
    #
    log "reset keystore as system user"
    keystore system r
    expect "1 No error"
    list_keystore_directory

    #
    # basic tests as system/root
    #
    log "root does not have permission to run test"
    keystore root t
    expect "6 Permission denied"
    
    log "but system user does"
    keystore system t
    expect "3 Uninitialized"
    list_keystore_directory

    log "password is now bar"
    keystore system p bar
    expect "1 No error"
    list_keystore_directory
    expect "-rw------- keystore keystore       84 .masterkey"
    
    log "no error implies initialized and unlocked"
    keystore system t
    expect "1 No error"
    
    log "saw with no argument"
    keystore system s
    expect "5 Protocol error"

    log "saw nothing"
    keystore system s ""
    expect "1 No error"

    log "add key baz"
    keystore system i baz quux
    expect "1 No error"

    log "1000 is uid of system"
    list_keystore_directory
    expect "-rw------- keystore keystore       84 .masterkey"
    expect "-rw------- keystore keystore       52 1000_baz"

    log "saw baz"
    keystore system s ""
    expect "1 No error"
    expect "baz"

    log "get baz"
    keystore system g baz
    expect "1 No error"
    expect "quux"

    log "root can read system user keys (as can wifi or vpn users)"
    keystore root g baz
    expect "1 No error"
    expect "quux"

    #
    # app user tests
    #

    # app_0 has uid 10000, as seen below
    log "other uses cannot see the system keys"
    keystore app_0 g baz
    expect "7 Key not found"
    
    log "app user cannot use reset, password, lock, unlock"
    keystore app_0 r
    expect "6 Permission denied"
    keystore app_0 p
    expect "6 Permission denied"
    keystore app_0 l
    expect "6 Permission denied"
    keystore app_0 u
    expect "6 Permission denied"

    log "install app_0 key"
    keystore app_0 i 0x deadbeef
    expect 1 No error
    list_keystore_directory
    expect "-rw------- keystore keystore       84 .masterkey"
    expect "-rw------- keystore keystore       52 10000_0x"
    expect "-rw------- keystore keystore       52 1000_baz"

    log "get with no argument"
    keystore app_0 g
    expect "5 Protocol error"
    
    keystore app_0 g 0x
    expect "1 No error"
    expect "deadbeef"
    
    keystore app_0 i fred barney
    expect "1 No error"
    
    keystore app_0 s ""
    expect "1 No error"
    expect "0x"
    expect "fred"

    log "note that saw returns the suffix of prefix matches"
    keystore app_0 s fr # fred
    expect "1 No error"
    expect "ed" # fred

    #
    # lock tests
    #
    log "lock the store as system"
    keystore system l
    expect "1 No error"
    keystore system t
    expect "2 Locked"
    
    log "saw works while locked"
    keystore app_0 s ""
    expect "1 No error"
    expect "0x"
    expect "fred"

    log "...but cannot read keys..."
    keystore app_0 g 0x
    expect "2 Locked"
    
    log "...but they can be deleted."
    keystore app_0 e 0x
    expect "1 No error"
    keystore app_0 d 0x
    expect "1 No error"
    keystore app_0 e 0x
    expect "7 Key not found"

    #
    # password
    #
    log "wrong password"
    keystore system u foo
    expect "13 Wrong password (4 tries left)"
    log "right password"
    keystore system u bar
    expect "1 No error"
    
    log "make the password foo"
    keystore system p foo
    expect "1 No error"
    
    #
    # final reset
    #
    log "reset wipes everything for all users"
    keystore system r
    expect "1 No error"
    list_keystore_directory
    
    keystore system t
    expect "3 Uninitialized"

}

function test_4599735() {
    # http://b/4599735
    log "start regression test for b/4599735"
    keystore system r
    expect "1 No error"

    keystore system p foo
    expect "1 No error"

    keystore system i baz quux
    expect "1 No error"
    
    keystore root g baz
    expect "1 No error"
    expect "quux"

    keystore system l
    expect "1 No error"

    keystore system p foo
    expect "1 No error"

    log "after unlock, regression led to result of '8 Value corrupted'"
    keystore root g baz
    expect "1 No error"
    expect "quux"

    keystore system r
    expect "1 No error"
    log "end regression test for b/4599735"
}

function main() {
    cleanup_output
    log $tag START
    test_basic
    test_4599735
    compare
    log $tag PASSED
    cleanup_output
}

main
